#include "logicmodel1.h"
#include<time.h>
#include<stdlib.h>

GameLogicModel::GameLogicModel()
    : mRow(kRow),
      mCol(kCol),
      totalMineCount(kMineCount),
      timerSeconds(kTime),
      gameState(In_progress)
{

}

GameLogicModel::~GameLogicModel()
{

}

void GameLogicModel::StartGame(int row, int col, int MineCount, GameLevel Level)
{
    Map.clear();

    mRow=row;
    mCol=col;
    totalMineCount=MineCount;
    CurMineCount=MineCount;
    gameState=In_progress;
    gameLevel=Level;
    timerSeconds=0;

    //初始化地图
    for(int i=0;i<mRow;i++)
    {
        std::vector<MineBlock> lineBlocks;
        for(int j=0;j<mCol;j++)
        {
            MineBlock mineBlock;
            mineBlock.CurState=Original;
            mineBlock.valueFlag=0;
            lineBlocks.push_back(mineBlock);
        }
        Map.push_back(lineBlocks);
    }

    //随机布雷
    srand((unsigned int)time(0));
    int k=totalMineCount;
    while(k>0)
    {
        int x=rand()%mRow;
        int y=rand()%mCol;
        if(Map[x][y].valueFlag!=-1)
        {
            Map[x][y].valueFlag=-1;
            k--;
        }
    }
    // 计算雷周围的方块数字
    for(int i = 0; i < mRow; i++)
    {
        for(int j = 0; j < mCol; j++)
        {
            // 周围八个方块（排除自己，在地图范围内）的数字根据雷的数目叠加
            // y为行偏移量，x为列偏移量
            // 前提：本方块不是雷
            if(Map[i][j].valueFlag != -1)
            {
                for(int y = -1; y <= 1; y++)
                {
                    for(int x = -1; x <= 1; x++)
                    {
                        if(i + y >= 0
                        && i + y < mRow
                        && j + x >= 0
                        && j + x < mCol
                        && Map[i + y][j + x].valueFlag == -1
                        && !(x == 0 && y == 0))
                        {
                            // 方块数字加1
                            Map[i][j].valueFlag++;
                        }
                    }
                }
            }
        }
    }
}

void GameLogicModel::Restart()
{
    StartGame(mRow,mCol,totalMineCount,gameLevel);
}
void GameLogicModel::OpenBlock(int m, int n)
{
    // 正常方块且没有被翻开过，标记为已挖
    if(Map[m][n].valueFlag > 0
     && Map[m][n].CurState == Original)
    {
        Map[m][n].CurState = Open;
    }

    // 遇到空白块（数字0）就递归挖雷，如果踩雷就爆掉,游戏结束
    if(Map[m][n].valueFlag == 0
     && Map[m][n].CurState == Original)
    {
        Map[m][n].CurState = Open;
        for(int y = -1; y <= 1; y++)
        {
            for(int x = -1; x <= 1; x++)
            {
                if(m + y >= 0
                && m + y < mRow
                && n + x >= 0
                && n + x < mCol
                && !(x == 0 && y == 0))
                {
                    OpenBlock(m + y, n + x);
                }
            }
        }
    }

    // 踩雷了
    if(Map[m][n].valueFlag == -1)
    {
        gameState = Over;
        Map[m][n].CurState = Bomb;
    }

    // 检查游戏输赢,并作调整
    CheckRes();
}
void GameLogicModel::CheckRes()
{
    // 游戏结束，显示所有雷
    if(gameState == Over)
    {
        // 输了就显示所有的雷以及标错的雷
        for(int i = 0; i < mRow; i++)
        {
            for(int j = 0; j < mCol; j++)
            {
                if(Map[i][j].valueFlag == -1)
                {
                    Map[i][j].CurState = Bomb;
                }
            }
        }
        return;
    }
    // 如果雷排完了，且所有方块都挖出或者标记
    if(gameState != Fault)
    {
        for(int i = 0; i < mRow; i++)
        {
            for(int j = 0; j < mCol; j++)
            {
                if(Map[i][j].CurState == Original)
                {
                    gameState = In_progress;
                    return;
                }
            }
        }
        // 否则既没有错误标记游戏状态又不是输或者进行中，游戏就是赢了
        gameState = Win;
    }
}


